package cn.zhentao.utils;

import com.aliyun.ocr_api20210707.Client;
import com.aliyun.ocr_api20210707.models.RecognizeAllTextRequest;
import com.aliyun.ocr_api20210707.models.RecognizeAllTextResponse;
import com.aliyun.tea.TeaException;
import com.aliyun.teaopenapi.models.Config;
import com.aliyun.teautil.models.RuntimeOptions;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.util.Base64;

/**
 * 阿里云OCR工具类
 * 基于阿里云OCR API 2021-07-07版本
 *
 * @author zhentao
 */
@Component
@Slf4j
public class AliyunOcrUtil {

    @Value("${aliyun.ocr.access-key-id}")
    private String accessKeyId;

    @Value("${aliyun.ocr.access-key-secret}")
    private String accessKeySecret;

    @Value("${aliyun.ocr.endpoint:ocr-api.cn-hangzhou.aliyuncs.com}")
    private String endpoint;

    private Client ocrClient;

    /**
     * 获取或初始化阿里云OCR客户端
     */
    private Client getOcrClient() {
        if (ocrClient == null) {
            synchronized (this) {
                if (ocrClient == null) {
                    try {
                        Config config = new Config()
                                .setAccessKeyId(accessKeyId)
                                .setAccessKeySecret(accessKeySecret);
                        config.endpoint = endpoint;

                        this.ocrClient = new Client(config);
                        log.info("阿里云OCR客户端初始化成功，endpoint: {}", endpoint);
                    } catch (Exception e) {
                        log.error("阿里云OCR客户端初始化失败: {}", e.getMessage(), e);
                        throw new RuntimeException("阿里云OCR客户端初始化失败", e);
                    }
                }
            }
        }
        return ocrClient;
    }

    /**
     * 通用文字识别 - 通过URL
     * 
     * @param imageUrl 图片URL
     * @return 识别结果JSON字符串
     */
    public String recognizeTextByUrl(String imageUrl) {
        return recognizeTextByUrl(imageUrl, "General");
    }

    /**
     * 通用文字识别 - 通过URL和类型
     * 
     * @param imageUrl 图片URL
     * @param type 识别类型 (General, IdCard, BankCard, BusinessLicense等)
     * @return 识别结果JSON字符串
     */
    public String recognizeTextByUrl(String imageUrl, String type) {
        try {
            log.info("开始识别图片文字，URL: {}, 类型: {}", imageUrl, type);
            
            RecognizeAllTextRequest request = new RecognizeAllTextRequest()
                    .setUrl(imageUrl)
                    .setType(type);
            
            RuntimeOptions runtime = new RuntimeOptions();
            runtime.setConnectTimeout(30000); // 30秒连接超时
            runtime.setReadTimeout(60000);    // 60秒读取超时
            
            RecognizeAllTextResponse response = getOcrClient().recognizeAllTextWithOptions(request, runtime);
            
            if (response != null && response.body != null && response.body.data != null) {
                String result = com.aliyun.teautil.Common.toJSONString(response.body.data);
                log.info("OCR识别成功，识别到 {} 个文字块", 
                    response.body.data.content != null ? response.body.data.content.length() : 0);
                return result;
            } else {
                log.warn("OCR识别返回空结果");
                return createEmptyResult("识别结果为空");
            }
            
        } catch (TeaException error) {
            log.error("阿里云OCR识别失败: {}", error.getMessage());
            log.error("诊断建议: {}", error.getData().get("Recommend"));
            throw new RuntimeException("OCR识别失败: " + error.getMessage());
        } catch (Exception error) {
            log.error("OCR识别异常: {}", error.getMessage(), error);
            throw new RuntimeException("OCR识别异常: " + error.getMessage());
        }
    }

    /**
     * 通用文字识别 - 通过文件流
     * 
     * @param inputStream 图片文件流
     * @param fileName 文件名
     * @return 识别结果JSON字符串
     */
    public String recognizeTextByStream(InputStream inputStream, String fileName) {
        return recognizeTextByStream(inputStream, fileName, "General");
    }

    /**
     * 通用文字识别 - 通过文件流和类型
     * 
     * @param inputStream 图片文件流
     * @param fileName 文件名
     * @param type 识别类型
     * @return 识别结果JSON字符串
     */
    public String recognizeTextByStream(InputStream inputStream, String fileName, String type) {
        try {
            log.info("开始识别图片文字，文件: {}, 类型: {}", fileName, type);
            
            // 将输入流转换为字节数组，然后创建新的输入流
            byte[] imageBytes = convertStreamToBytes(inputStream);

            RecognizeAllTextRequest request = new RecognizeAllTextRequest()
                    .setBody(new ByteArrayInputStream(imageBytes))
                    .setType(type);
            
            RuntimeOptions runtime = new RuntimeOptions();
            runtime.setConnectTimeout(30000);
            runtime.setReadTimeout(60000);
            
            RecognizeAllTextResponse response = getOcrClient().recognizeAllTextWithOptions(request, runtime);
            
            if (response != null && response.body != null && response.body.data != null) {
                String result = com.aliyun.teautil.Common.toJSONString(response.body.data);
                log.info("OCR识别成功，文件: {}", fileName);
                return result;
            } else {
                log.warn("OCR识别返回空结果，文件: {}", fileName);
                return createEmptyResult("识别结果为空");
            }
            
        } catch (TeaException error) {
            log.error("阿里云OCR识别失败，文件: {}, 错误: {}", fileName, error.getMessage());
            log.error("诊断建议: {}", error.getData().get("Recommend"));
            throw new RuntimeException("OCR识别失败: " + error.getMessage());
        } catch (Exception error) {
            log.error("OCR识别异常，文件: {}, 错误: {}", fileName, error.getMessage(), error);
            throw new RuntimeException("OCR识别异常: " + error.getMessage());
        }
    }

    /**
     * 身份证识别 - 通过URL
     */
    public String recognizeIdCardByUrl(String imageUrl) {
        return recognizeTextByUrl(imageUrl, "IdCard");
    }

    /**
     * 身份证识别 - 通过文件流
     */
    public String recognizeIdCardByStream(InputStream inputStream, String fileName) {
        return recognizeTextByStream(inputStream, fileName, "IdCard");
    }

    /**
     * 银行卡识别 - 通过URL
     */
    public String recognizeBankCardByUrl(String imageUrl) {
        return recognizeTextByUrl(imageUrl, "BankCard");
    }

    /**
     * 银行卡识别 - 通过文件流
     */
    public String recognizeBankCardByStream(InputStream inputStream, String fileName) {
        return recognizeTextByStream(inputStream, fileName, "BankCard");
    }

    /**
     * 营业执照识别 - 通过URL
     */
    public String recognizeBusinessLicenseByUrl(String imageUrl) {
        return recognizeTextByUrl(imageUrl, "BusinessLicense");
    }

    /**
     * 营业执照识别 - 通过文件流
     */
    public String recognizeBusinessLicenseByStream(InputStream inputStream, String fileName) {
        return recognizeTextByStream(inputStream, fileName, "BusinessLicense");
    }

    /**
     * 将输入流转换为字节数组
     */
    private byte[] convertStreamToBytes(InputStream inputStream) throws Exception {
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        byte[] buffer = new byte[1024];
        int length;
        while ((length = inputStream.read(buffer)) != -1) {
            outputStream.write(buffer, 0, length);
        }
        return outputStream.toByteArray();
    }

    /**
     * 将输入流转换为Base64字符串
     */
    private String convertStreamToBase64(InputStream inputStream) throws Exception {
        byte[] imageBytes = convertStreamToBytes(inputStream);
        return Base64.getEncoder().encodeToString(imageBytes);
    }

    /**
     * 创建空结果
     */
    private String createEmptyResult(String reason) {
        return String.format("{\"success\":false,\"message\":\"%s\",\"content\":\"\",\"results\":[]}", reason);
    }

    /**
     * 获取客户端实例（用于高级用法）
     */
    public Client getClient() {
        return getOcrClient();
    }
}
